package com.imut.lagain.service.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imut.lagain.service.ICacheService;
import com.imut.lagain.service.ISmsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern;

/**
 * 短信服务实现类
 * 提供短信发送功能
 */
@Service
public class SmsServiceImpl implements ISmsService {
    private static final Logger log = LoggerFactory.getLogger(SmsServiceImpl.class);

    
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;
    
    @Autowired(required = false)
    private ICacheService cacheService;
    
    public SmsServiceImpl(RestTemplate restTemplate, ObjectMapper objectMapper) {
        this.restTemplate = restTemplate;
        this.objectMapper = objectMapper;
    }
    
    @Value("${sms.provider:aliyun}")
    private String smsProvider;
    
    @Value("${sms.aliyun.accessKeyId:}")
    private String aliyunAccessKeyId;
    
    @Value("${sms.aliyun.accessKeySecret:}")
    private String aliyunAccessKeySecret;
    
    @Value("${sms.aliyun.signName:时光胶囊}")
    private String aliyunSignName;
    
    @Value("${sms.aliyun.endpoint:https://dysmsapi.aliyuncs.com}")
    private String aliyunEndpoint;
    
    @Value("${sms.tencent.secretId:}")
    private String tencentSecretId;
    
    @Value("${sms.tencent.secretKey:}")
    private String tencentSecretKey;
    
    @Value("${sms.tencent.appId:}")
    private String tencentAppId;
    
    @Value("${sms.tencent.signName:时光胶囊}")
    private String tencentSignName;
    
    @Value("${sms.enabled:false}")
    private boolean smsEnabled;
    
    @Value("${sms.rateLimit.perMinute:5}")
    private int rateLimitPerMinute;
    
    @Value("${sms.rateLimit.perHour:20}")
    private int rateLimitPerHour;
    
    @Value("${sms.rateLimit.perDay:50}")
    private int rateLimitPerDay;
    private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");
    private static final String TEMPLATE_VERIFICATION_CODE = "SMS_001";
    private static final String TEMPLATE_LOGIN_NOTIFICATION = "SMS_002";
    private static final String TEMPLATE_CAPSULE_REMINDER = "SMS_003";
    private static final String TEMPLATE_SECURITY_ALERT = "SMS_004";
    /**
     * 发送短信
     * @param phone 手机号
     * @param templateId 模板ID
     * @param params 模板参数
     * @return 是否发送成功
     */
    public boolean sendSms(String phone, String templateId, Map<String, String> params) {
        try {
            if (!smsEnabled) {
                log.warn("短信服务未启用");
                return false;
            }
            if (!isValidPhone(phone)) {
                log.warn("手机号格式无效: {}", phone);
                return false;
            }
            if (!checkRateLimit(phone)) {
                log.warn("短信发送频率超限: {}", phone);
                return false;
            }
            boolean success = false;
            switch (smsProvider.toLowerCase()) {
                case "aliyun":
                    success = sendAliyunSms(phone, templateId, params);
                    break;
                case "tencent":
                    success = sendTencentSms(phone, templateId, params);
                    break;
                default:
                    log.error("不支持的短信服务商: {}", smsProvider);
                    return false;
            }
            if (success) {
                recordSmsSuccess(phone, templateId);
            } else {
                recordSmsFailure(phone, templateId);
                log.error("短信发送失败: phone={}, template={}", phone, templateId);
            }
            
            return success;
        } catch (Exception e) {
            log.error("短信发送异常: phone={}, template={}", phone, templateId, e);
            recordSmsFailure(phone, templateId);
            return false;
        }
    }
    
    /**
     * 异步发送短信
     * @param phone 手机号
     * @param templateId 模板ID
     * @param params 模板参数
     * @return CompletableFuture
     */
    public CompletableFuture<Boolean> sendSmsAsync(String phone, String templateId, Map<String, String> params) {
        return CompletableFuture.supplyAsync(() -> sendSms(phone, templateId, params));
    }
    /**
     * 发送阿里云短信
     * @param phone 手机号
     * @param templateId 模板ID
     * @param params 模板参数
     * @return 是否发送成功
     */
    private boolean sendAliyunSms(String phone, String templateId, Map<String, String> params) {
        try {
            Map<String, String> requestParams = new HashMap<>();
            requestParams.put("PhoneNumbers", phone);
            requestParams.put("SignName", aliyunSignName);
            requestParams.put("TemplateCode", templateId);
            if (params != null && !params.isEmpty()) {
                requestParams.put("TemplateParam", objectMapper.writeValueAsString(params));
            }
            requestParams.put("AccessKeyId", aliyunAccessKeyId);
            requestParams.put("Action", "SendSms");
            requestParams.put("Version", "2017-05-25");
            requestParams.put("RegionId", "cn-hangzhou");
            requestParams.put("Format", "JSON");
            requestParams.put("SignatureMethod", "HMAC-SHA1");
            requestParams.put("SignatureVersion", "1.0");
            requestParams.put("SignatureNonce", String.valueOf(System.currentTimeMillis()));
            requestParams.put("Timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")));
            String signature = generateAliyunSignature(requestParams);
            requestParams.put("Signature", signature);
            HttpHeaders headers = new HttpHeaders();
            headers.set("Content-Type", "application/x-www-form-urlencoded");
            
            StringBuilder body = new StringBuilder();
            for (Map.Entry<String, String> entry : requestParams.entrySet()) {
                if (body.length() > 0) {
                    body.append("&");
                }
                body.append(entry.getKey()).append("=").append(entry.getValue());
            }
            
            HttpEntity<String> entity = new HttpEntity<>(body.toString(), headers);
            ResponseEntity<String> response = restTemplate.exchange(
                aliyunEndpoint, HttpMethod.POST, entity, String.class);
            JsonNode responseJson = objectMapper.readTree(response.getBody());
            String code = responseJson.path("Code").asText();
            
            return "OK".equals(code);
        } catch (Exception e) {
            log.error("阿里云短信发送失败", e);
            return false;
        }
    }
    
    /**
     * 生成阿里云签名（简化版本）
     * @param params 参数
     * @return 签名
     */
    private String generateAliyunSignature(Map<String, String> params) {
        return "mock_signature_" + System.currentTimeMillis();
    }
    /**
     * 发送腾讯云短信
     * @param phone 手机号
     * @param templateId 模板ID
     * @param params 模板参数
     * @return 是否发送成功
     */
    private boolean sendTencentSms(String phone, String templateId, Map<String, String> params) {
        try {
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("PhoneNumberSet", new String[]{phone});
            requestBody.put("SmsSdkAppId", tencentAppId);
            requestBody.put("SignName", tencentSignName);
            requestBody.put("TemplateId", templateId);
            
            if (params != null && !params.isEmpty()) {
                requestBody.put("TemplateParamSet", params.values().toArray(new String[0]));
            }
            HttpHeaders headers = new HttpHeaders();
            headers.set("Content-Type", "application/json");
            headers.set("Authorization", generateTencentAuth());
            
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
            String url = "https://sms.tencentcloudapi.com/";
            ResponseEntity<String> response = restTemplate.exchange(
                url, HttpMethod.POST, entity, String.class);
            JsonNode responseJson = objectMapper.readTree(response.getBody());
            JsonNode error = responseJson.path("Response").path("Error");
            
            return error.isMissingNode();
        } catch (Exception e) {
            log.error("腾讯云短信发送失败", e);
            return false;
        }
    }
    
    /**
     * 生成腾讯云认证头（简化版本）
     * @return 认证头
     */
    private String generateTencentAuth() {
        return "TC3-HMAC-SHA256 Credential=" + tencentSecretId + "/mock_auth";
    }
    /**
     * 发送验证码短信
     * @param phone 手机号
     * @param code 验证码
     * @return 是否发送成功
     */
    public boolean sendVerificationCode(String phone, String code) {
        Map<String, String> params = new HashMap<>();
        params.put("code", code);
        params.put("expire", "5"); // 5分钟过期
        
        return sendSms(phone, TEMPLATE_VERIFICATION_CODE, params);
    }
    
    /**
     * 发送登录验证码
     * @param phone 手机号
     * @param code 验证码
     * @return 是否发送成功
     */
    public boolean sendLoginCode(String phone, String code) {
        Map<String, String> params = new HashMap<>();
        params.put("code", code);
        params.put("expire", "5"); // 5分钟过期
        
        return sendSms(phone, TEMPLATE_VERIFICATION_CODE, params);
    }
    
    /**
     * 发送注册验证码
     * @param phone 手机号
     * @param code 验证码
     * @return 是否发送成功
     */
    public boolean sendRegisterCode(String phone, String code) {
        Map<String, String> params = new HashMap<>();
        params.put("code", code);
        params.put("expire", "5"); // 5分钟过期
        
        return sendSms(phone, TEMPLATE_VERIFICATION_CODE, params);
    }
    
    /**
     * 发送密码重置验证码
     * @param phone 手机号
     * @param code 验证码
     * @return 是否发送成功
     */
    public boolean sendPasswordResetCode(String phone, String code) {
        Map<String, String> params = new HashMap<>();
        params.put("code", code);
        params.put("expire", "5"); // 5分钟过期
        
        return sendSms(phone, TEMPLATE_VERIFICATION_CODE, params);
    }

    @Override
    public boolean sendCapsuleOpenNotification(String phone, String capsuleTitle) {
        return false;
    }

    @Override
    public boolean sendCapsuleOpenReminder(String phone, String capsuleTitle, int daysLeft) {
        return false;
    }

    /**
     * 发送胶囊提醒短信
     * @param phone 手机号
     * @param capsuleTitle 胶囊标题
     * @param message 消息内容
     * @return 是否发送成功
     */
    @Override
    public boolean sendCapsuleReminder(String phone, String capsuleTitle, String message) {
        Map<String, String> params = new HashMap<>();
        params.put("title", capsuleTitle);
        params.put("message", message);
        
        return sendSms(phone, TEMPLATE_CAPSULE_REMINDER, params);
    }
    
    /**
     * 发送安全警告短信
     * @param phone 手机号
     * @param action 操作类型
     * @param ip IP地址
     * @return 是否发送成功
     */
    public boolean sendSecurityAlert(String phone, String action, String ip) {
        Map<String, String> params = new HashMap<>();
        params.put("action", action);
        params.put("ip", ip);
        params.put("time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("MM-dd HH:mm")));
        
        return sendSms(phone, TEMPLATE_SECURITY_ALERT, params);
    }
    
    /**
     * 发送系统通知短信
     * @param phone 手机号
     * @param message 通知消息
     * @return 是否发送成功
     */
    public boolean sendSystemNotification(String phone, String message) {
        if (!isValidPhone(phone)) {
            log.warn("无效的手机号: {}", phone);
            return false;
        }
        
        Map<String, String> params = new HashMap<>();
        params.put("message", message);
        params.put("time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        
        return sendSms(phone, "SMS_SYSTEM", params);
    }
    /**
     * 验证手机号格式
     * @param phone 手机号
     * @return 是否有效
     */
    public boolean isValidPhone(String phone) {
        return StringUtils.hasText(phone) && PHONE_PATTERN.matcher(phone).matches();
    }
    
    /**
     * 检查发送频率限制
     * @param phone 手机号
     * @return 是否允许发送
     */
    public boolean checkRateLimit(String phone) {
        try {
            String minuteKey = "sms:rate:minute:" + phone;
            String hourKey = "sms:rate:hour:" + phone;
            String dayKey = "sms:rate:day:" + phone;
            long minuteCount = cacheService.increment(minuteKey, 1);
            if (minuteCount == 1) {
                cacheService.expire(minuteKey, 60, java.util.concurrent.TimeUnit.SECONDS);
            }
            if (minuteCount > rateLimitPerMinute) {
                return false;
            }
            long hourCount = cacheService.increment(hourKey, 1);
            if (hourCount == 1) {
                cacheService.expire(hourKey, 1, java.util.concurrent.TimeUnit.HOURS);
            }
            if (hourCount > rateLimitPerHour) {
                return false;
            }
            long dayCount = cacheService.increment(dayKey, 1);
            if (dayCount == 1) {
                cacheService.expire(dayKey, 24, java.util.concurrent.TimeUnit.HOURS);
            }
            if (dayCount > rateLimitPerDay) {
                return false;
            }
            
            return true;
        } catch (Exception e) {
            log.error("检查短信发送频率限制失败", e);
            return false;
        }
    }
    
    /**
     * 记录短信发送成功
     * @param phone 手机号
     * @param templateId 模板ID
     */
    private void recordSmsSuccess(String phone, String templateId) {
        try {
            String key = "sms:success:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            cacheService.increment(key, 1);
            cacheService.expire(key, 7, java.util.concurrent.TimeUnit.DAYS);
        } catch (Exception e) {
            log.error("记录短信发送成功失败", e);
        }
    }
    
    /**
     * 记录短信发送失败
     * @param phone 手机号
     * @param templateId 模板ID
     */
    private void recordSmsFailure(String phone, String templateId) {
        try {
            String key = "sms:failure:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            cacheService.increment(key, 1);
            cacheService.expire(key, 7, java.util.concurrent.TimeUnit.DAYS);
        } catch (Exception e) {
            log.error("记录短信发送失败失败", e);
        }
    }
    
    /**
     * 获取短信发送统计
     * @param date 日期
     * @return 统计信息
     */
    public Map<String, Object> getSmsStatistics(String date) {
        try {
            String successKey = "sms:success:" + date;
            String failureKey = "sms:failure:" + date;
            
            Object successCount = cacheService.get(successKey);
            Object failureCount = cacheService.get(failureKey);
            
            Map<String, Object> statistics = new HashMap<>();
            statistics.put("date", date);
            statistics.put("successCount", successCount != null ? successCount : 0);
            statistics.put("failureCount", failureCount != null ? failureCount : 0);
            
            return statistics;
        } catch (Exception e) {
            log.error("获取短信发送统计失败", e);
            return Map.of();
        }
    }
    
    /**
     * 检查短信服务是否可用
     * @return 是否可用
     */
    public boolean isSmsServiceAvailable() {
        return smsEnabled && StringUtils.hasText(smsProvider);
    }
    
    @Override
    public Map<String, Object> getSmsStats(String phone) {
        Map<String, Object> stats = new HashMap<>();
        
        try {
            String todayKey = "sms:stats:" + phone + ":" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            Object todayCountObj = cacheService.get(todayKey);
            stats.put("todayCount", todayCountObj != null ? Integer.parseInt(todayCountObj.toString()) : 0);
            String hourKey = "sms:stats:" + phone + ":" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH"));
            Object hourCountObj = cacheService.get(hourKey);
            stats.put("hourCount", hourCountObj != null ? Integer.parseInt(hourCountObj.toString()) : 0);
            String minuteKey = "sms:stats:" + phone + ":" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm"));
            Object minuteCountObj = cacheService.get(minuteKey);
            stats.put("minuteCount", minuteCountObj != null ? Integer.parseInt(minuteCountObj.toString()) : 0);
            stats.put("rateLimitPerMinute", rateLimitPerMinute);
            stats.put("rateLimitPerHour", rateLimitPerHour);
            stats.put("rateLimitPerDay", rateLimitPerDay);
            
            return stats;
        } catch (Exception e) {
            log.error("获取短信统计失败: {}", e.getMessage());
            return new HashMap<>();
        }
    }
}

